#pragma once
#include<iostream>
#include<string>

class Shape_Interface
{
public:
	virtual void Draw() = 0;
};

class Circle_Implementation :public Shape_Interface
{
public:
	void Draw() override
	{
		std::cout << "Inside Circle draw() method" << std::endl;
	}
};

class Rectangle_Implementation :public Shape_Interface
{
public:
	void Draw() override
	{
		std::cout << "Inside Rectangle draw() method" << std::endl;
	}
};

class Square_Implementation :public Shape_Interface
{
public:
	void Draw() override
	{
		std::cout << "Inside Square draw() method" << std::endl;
	}
};

class Color_Interface
{
public:
	virtual void Fill() = 0;
};

class Red_Implementation :public Color_Interface
{
public:
	void Fill()override
	{
		std::cout << "Inside Red Fill method" << std::endl;
	}
};

class Green_Implementation :public Color_Interface
{
public:
	void Fill()override
	{
		std::cout << "Inside Green Fill method" << std::endl;
	}
};

class Blue_Implementation :public Color_Interface
{
public:
	void Fill()override
	{
		std::cout << "Inside Blue Fill method" << std::endl;
	}
};

class AbstractFactory_Abstract
{
public:
	virtual Shape_Interface* GetShape(std::string ShapeType)
	{
		return nullptr;
	}
	virtual Color_Interface* GetColor(std::string ColorType)
	{
		return nullptr;
	}
};

class ShapeFactory_Extend:public AbstractFactory_Abstract
{
public:
	Shape_Interface* GetShape(std::string ShapeType)
	{
		if (ShapeType == "Circle")
		{
			Shape_Interface* Instance = new Circle_Implementation();
			return Instance;
		}
		else if (ShapeType == "Rectangle")
		{
			Shape_Interface* Instance = new Rectangle_Implementation();
			return Instance;
		}
		else if (ShapeType == "Square")
		{
			Shape_Interface* Instance = new Square_Implementation();
			return Instance;
		}
		return nullptr;
	}
};

class ColorFactory_Extend:public AbstractFactory_Abstract
{
public:
	Color_Interface* GetColor(std::string ColorType)
	{
		if (ColorType == "Red")
		{
			Color_Interface* Instance = new Red_Implementation();
			return Instance;
		}
		else if (ColorType == "Green")
		{
			Color_Interface* Instance = new Green_Implementation();
			return Instance;
		}
		else if (ColorType == "Blue")
		{
			Color_Interface* Instance = new Blue_Implementation();
			return Instance;
		}
		return nullptr;
	}
};

class FactoryProducer
{
public:
	static AbstractFactory_Abstract* GetFactory(std::string FactoryType)
	{
		if (FactoryType == "Shape")
		{
			AbstractFactory_Abstract* Instance = new ShapeFactory_Extend();
			return Instance;
		}
		else if (FactoryType == "Color")
		{
			AbstractFactory_Abstract* Instance = new ColorFactory_Extend();
			return Instance;
		}
		return nullptr;
	}
};